package com.xcc.dataStructures.leetcode;


import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * n皇后问题 研究的是如何将 n个皇后放置在 n×n 的棋盘上，并且使皇后彼此之间不能相互攻击。
 * 给你一个整数 n ，返回所有不同的n皇后问题 的解决方案。
 * 每一种解法包含一个不同的n 皇后问题 的棋子放置方案，该方案中 'Q' 和 '.' 分别代表了皇后和空位。
 *
 * 输入：n = 4
 * 输出：[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
 * 解释：如上图所示，4 皇后问题存在两个不同的解法。
 *
 * 1 <= n <= 9
 * 皇后彼此不能相互攻击，也就是说：任何两个皇后都不能处于同一条横行、纵行或斜线上。
 *
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/n-queens
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 */
public class Demo010_NQueen {

    public static void main(String[] args) {
        Demo010_NQueen demo010_nQueen = new Demo010_NQueen();
        System.out.println(demo010_nQueen.solveNQueens(5));
    }

    public List<List<String>> solveNQueens(int n) {
        Queen queen = new Queen(n);
        queen.check(0);
//        System.out.println(queen.res);
        return queen.res;
    }

}

class Queen{

    private int size;
    //表示每行的数据存储在哪里
    private int[] arr;
    //最终返回的结果
    List<List<String>> res= new ArrayList<>();

    public Queen(int size) {
        this.size = size;
    }

    /**
     * 加入第num个皇后(从0开始)
     */
    public void check(int num) {
        //当存放第0个皇后时，初始化数组
        if (num == 0) {
            arr = new int[size];
        }
        if (num == size ) {
            //拼装满足条件的字符串集合
            List<String> list = new ArrayList<>();
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < size; i++) {
                //清空sb
                sb.delete(0, sb.length());
                for (int j = 0; j < size ; j++) {
                    if (j == arr[i]) {
                        sb.append('Q');
                    } else {
                        sb.append('.');
                    }
                }
                list.add(sb.toString());
            }

            res.add(list);
//            System.out.println(Arrays.toString(arr));
            return ;
        }

        for (int i = 0; i < size; i++) {
            //当前放置的皇后，每次会从0开始选择
            arr[num] = i;
            //上一步放置完成之后，接下来就会校验索引为num的这个数值是否合理
            if (judge(num)) {
                check(num + 1);
            }
        }
    }

    /**
     * 判断当前皇后放的位置是否合适
     * @param i 当前皇后对应的索引
     * @return
     */
    private boolean judge(int i) {
        for (int j = 0; j < i; j++) {
            int index = Math.abs(i - j);
            int val = Math.abs(arr[i] - arr[j]);
            if (val == index || i == j || arr[i] == arr[j]) {
                return false;
            }
        }
        return true;
    }
}
